package gold.digger;

import gold.utils.InputUtil;

import java.util.*;
import java.util.stream.Collectors;

/**
 * Created by fanzhenyu02 on 2021/12/10.
 * common problem solver template.
 */
public class LC1610 {
    public long startExecuteTime = System.currentTimeMillis();

    class Solution {
        public int visiblePoints(List<List<Integer>> points, int angle, List<Integer> location) {
            int x = location.get(0), y = location.get(1);
            List<Double> list = new ArrayList<>();
            int cnt = 0;
            double pi = Math.PI, t = angle * pi / 180;
            for (List<Integer> p : points) {
                int a = p.get(0), b = p.get(1);
                if (a == x && b == y && ++cnt >= 0) continue;
                list.add(Math.atan2(b - y, a - x) + pi);
            }
            Collections.sort(list);
            int n = list.size(), max = 0;
            for (int i = 0; i < n; i++) list.add(list.get(i) + 2 * pi);
            for (int i = 0, j = 0; j < 2 * n; j++) {
                while (i < j && list.get(j) - list.get(i) > t) i++;
                max = Math.max(max, j - i + 1);
            }
            return cnt + max;
        }
    }


    class Solution_Hard_To_Debug_To_Fix {
        public int visiblePoints(List<List<Integer>> points, int angle, List<Integer> location) {
            TreeMap<Double, Integer> coordinateMap = new TreeMap<>();
            int standCnt = 0;
            for (List<Integer> point : points) {
                double curAngle = 0;
                if (point.get(0) == location.get(0)) {
                    if (point.get(1) != location.get(1)) curAngle = point.get(1) > location.get(1) ? 90 : 270;
                    else {
                        ++standCnt;
                        continue;
                    }
                } else {
                    curAngle = Math.toDegrees(Math.atan((point.get(1) - location.get(1)) / (point.get(0) - location.get(0))));
                }

                coordinateMap.put(curAngle, coordinateMap.getOrDefault(curAngle, 0) + 1);
            }

            final List<Double> angleList = coordinateMap.keySet().stream().collect(Collectors.toList());
            int maxSum = 0, curSum = 0, i = 0, j = 1;
            while (i < angleList.size()) {
                j = i;
                while (j < angleList.size() && angleList.get(j) - angleList.get(i) <= angle) {
                    curSum += coordinateMap.get(angleList.get(j++));
                }
                maxSum = Math.max(maxSum, curSum);
                curSum = 0;
                ++i;
            }

            return maxSum + standCnt;
        }
    }

    public void run() {
        Solution solution = new Solution();

//        System.out.println(Math.tan(Math.toRadians(45)));
//        System.out.println(Math.toDegrees(Math.atan(1)));


//        输入：points = [[2,1],[2,2],[3,3]], angle = 90, location = [1,1]
//        输出：3
//        解释：阴影区域代表你的视野。在你的视野中，所有的点都清晰可见，尽管 [2,2] 和 [3,3]在同一条直线上，你仍然可以看到 [3,3] 。
//        List<List<Integer>> arr = InputUtil.toDoubleIntegerList("[[2,1],[2,2],[3,3]]");
//        System.out.println(solution.visiblePoints(arr, 90, Arrays.asList(1, 1)));


//        输入：points = [[2,1],[2,2],[3,4],[1,1]], angle = 90, location = [1,1]
//        输出：4
//        解释：在你的视野中，所有的点都清晰可见，包括你所在位置的那个点。
//        List<List<Integer>> arr = InputUtil.toDoubleIntegerList("[[2,1],[2,2],[3,4],[1,1]]");
//        System.out.println(solution.visiblePoints(arr, 90, Arrays.asList(1, 1)));

//        输入：points = [[1,0],[2,1]], angle = 13, location = [1,1]
//        输出：1
//        解释：如图所示，你只能看到两点之一。
        List<List<Integer>> arr = InputUtil.toDoubleIntegerList("[[1,0],[2,1]]");
        System.out.println(solution.visiblePoints(arr, 13, Arrays.asList(1, 1)));


    }

    public static void main(String[] args) throws Exception {
        LC1610 an = new LC1610();
        an.run();

        System.out.println("\ncurrent solution total execute time: " + (System.currentTimeMillis() - an.startExecuteTime) + " ms.");
    }
}
